package com.jifeng.api.wxpay.controller;


import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.jifeng.api.crud.constant.FieldConstant;
import com.jifeng.api.crud.entity.FeeLogEntity;
import com.jifeng.api.crud.entity.OrderEntity;
import com.jifeng.api.crud.entity.TerminalEntity;
import com.jifeng.api.crud.service.FeeLogService;
import com.jifeng.api.crud.service.OrderService;
import com.jifeng.api.crud.service.TerminalService;
import com.jifeng.api.utils.R;
import com.jifeng.api.wxpay.config.WxProgramPayConfig;
import com.jifeng.api.wxpay.sdk.PaymentApi;
import com.jifeng.api.wxpay.sdk.PaymentKit;
import com.jifeng.api.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.net.InetAddress;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Service
public class PayService {

    @Autowired
    OrderService orderService;

    @Autowired
    TerminalService terminalService;

    @Autowired
    FeeLogService feeLogService;


    public void setProjectName(String projectName) {
        projectName = projectName;
    }

    public String getRequestUrl() {
        return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest().getRequestURI();
    }

    /**
     * 功能描述: <调用统一下单的接口>
     **/
    public R unifiedOrder(String outTradeNo, Integer money, String openid, String terminalId, String mobile) throws Exception {
        Map<String, String> reqParams = new HashMap<>();
        //微信分配的小程序ID
        reqParams.put("appid", WxProgramPayConfig.APPID);
        //微信支付分配的商户号
        reqParams.put("mch_id", WxProgramPayConfig.MCH_ID);
        //随机字符串
        reqParams.put("nonce_str", System.currentTimeMillis() / 1000 + "");
        //签名类型
        reqParams.put("sign_type", "MD5");
        //充值订单 商品描述
        reqParams.put("body", "优倍护-租赁");

        //商户订单号
        reqParams.put("out_trade_no", outTradeNo);
        //订单总金额，单位为分
        reqParams.put("total_fee",String.valueOf(money));
        //终端IP
        InetAddress addr = InetAddress.getLocalHost();
        String spbill_create_ip = addr.getHostAddress();
        reqParams.put("spbill_create_ip", spbill_create_ip);
        //通知地址
        reqParams.put("notify_url", WxProgramPayConfig.START_NOTIFY_URL);
        //交易类型
        reqParams.put("trade_type", "JSAPI");
        //用户标识
        reqParams.put("openid", openid);
        //附加参数
//        reqParams.put("attach", test);
        //签名
        String sign = WXPayUtil.generateSignature(reqParams, WxProgramPayConfig.KEY);
        reqParams.put("sign", sign);
        /*
            调用支付定义下单API,返回预付单信息 prepay_id
         */
        String xmlResult = PaymentApi.pushOrder(reqParams);
        log.info("xmlResult:\n{}", xmlResult);
        Map<String, String> result = PaymentKit.xmlToMap(xmlResult);
        String returnCode = result.get("return_code");
        String resultCode = result.get("result_code");
        boolean isHasPrepayId = result.containsKey("prepay_id");

        OrderEntity orderEntity = orderService.getById(outTradeNo);
        if (orderEntity == null) {
            log.warn("path：{}，errMsg：{}", getRequestUrl(), "不存在租赁改机柜的订单");
            return R.error(400, "不存在租赁改机柜的订单");
        }

        /**
         * 支付失败
         */
        if (returnCode.equals("FAIL") || !isHasPrepayId || resultCode.equals("FAIL")) {

            /**
             * 往支付日志表中插入数据
             */
            FeeLogEntity feeLogEntity = new FeeLogEntity();
            feeLogEntity.setOrderId(Long.parseLong(outTradeNo) );
            feeLogEntity.setFee(money);
            feeLogEntity.setPaidFee(0);
            feeLogEntity.setMemo("支付失败");
            boolean saveRs = feeLogService.save(feeLogEntity);
            if (!saveRs){
                log.warn("path：{}，errMsg：{}", getRequestUrl(), "支付日志保存失败");
            }

            orderEntity.setComState(5);
            orderEntity.setRevTime(new Date());
            boolean updateOrderRs = orderService.updateById(orderEntity);
            if (!updateOrderRs) {
                log.warn("path：{}，errMsg：{}", getRequestUrl(), "更新订单失败");
            }
            TerminalEntity terminalEntity = new TerminalEntity();
            terminalEntity.setRentState(0);
            boolean updateTerminalRs = terminalService.update(terminalEntity,new UpdateWrapper<TerminalEntity>().eq(FieldConstant.T_TERMINAL_IOT,terminalId));
            if (!updateTerminalRs) {
                log.warn("path：{}，errMsg：{}", getRequestUrl(), "更新机柜失败");
            }
            log.warn("path：{}，errMsg：{}", getRequestUrl(), "支付失败");
            return R.error("支付失败");
        }
        //预付单信息
        String prepay_id = result.get("prepay_id");

        /**
         * 小程序调起支付数据签名
         */
        Map<String, String> packageParams = new HashMap<String, String>();
        packageParams.put("appId", WxProgramPayConfig.APPID);
        packageParams.put("timeStamp", System.currentTimeMillis() / 1000 + "");
        packageParams.put("nonceStr", System.currentTimeMillis() + "");
        packageParams.put("package", "prepay_id=" + prepay_id);
        packageParams.put("signType", "MD5");
        String packageSign = WXPayUtil.generateSignature(packageParams, WxProgramPayConfig.KEY);
        packageParams.put("paySign", packageSign);
        return R.ok().put("data", packageParams);
    }

    public R endUnifiedOrder(String outTradeNo, Integer money, String openid, String terminalId, String mobile,String orderId) throws Exception {
        Map<String, String> reqParams = new HashMap<>();
        //微信分配的小程序ID
        reqParams.put("appid", WxProgramPayConfig.APPID);
        //微信支付分配的商户号
        reqParams.put("mch_id", WxProgramPayConfig.MCH_ID);
        //随机字符串
        reqParams.put("nonce_str", System.currentTimeMillis() / 1000 + "");
        //签名类型
        reqParams.put("sign_type", "MD5");
        //充值订单 商品描述
        reqParams.put("body", "优倍护-欠费归还");

        //商户订单号
        reqParams.put("out_trade_no", outTradeNo);
        //订单总金额，单位为分
        reqParams.put("total_fee", money.toString());
//        reqParams.put("total_fee", money.multiply(BigDecimal.valueOf(100)).intValue() + "");
        //终端IP
        InetAddress addr = InetAddress.getLocalHost();
        String spbill_create_ip = addr.getHostAddress();
        reqParams.put("spbill_create_ip", spbill_create_ip);
        //通知地址
        reqParams.put("notify_url", WxProgramPayConfig.END_NOTIFY_URL);
        //交易类型
        reqParams.put("trade_type", "JSAPI");
        //用户标识
        reqParams.put("openid", openid);
        //附加参数
        reqParams.put("attach", orderId);
        //签名
        String sign = WXPayUtil.generateSignature(reqParams, WxProgramPayConfig.KEY);
        reqParams.put("sign", sign);
        /*
            调用支付定义下单API,返回预付单信息 prepay_id
         */
        String xmlResult = PaymentApi.pushOrder(reqParams);
        log.info("xmlResult->>>>>>>>{}", xmlResult);
        Map<String, String> result = PaymentKit.xmlToMap(xmlResult);

        String returnCode = result.get("return_code");
        String resultCode = result.get("result_code");
        boolean isHasPrepayId = result.containsKey("prepay_id");

        OrderEntity orderEntity = orderService.getById(orderId);
        if (orderEntity == null) {
            log.warn("path：{}，errMsg：{}", getRequestUrl(), "不存在租赁改机柜的订单");
            return R.error(400, "不存在租赁改机柜的订单");
        }

        /**
         * 微信支付失败
         */
        if (returnCode.equals("FAIL") || !isHasPrepayId || resultCode.equals("FAIL")) {

            FeeLogEntity feeLogEntity = new FeeLogEntity();
            feeLogEntity.setOrderId(Long.parseLong(outTradeNo) );
            feeLogEntity.setFee(money);
            feeLogEntity.setPaidFee(0);
            feeLogEntity.setMemo("支付失败");
            boolean saveRs = feeLogService.save(feeLogEntity);
            if (!saveRs){
                log.warn("path：{}，errMsg：{}", getRequestUrl(), "支付日志保存失败");
            }

            orderEntity.setComState(5);
            orderEntity.setRevTime(new Date());
            boolean updateOrderRs = orderService.updateById(orderEntity);
            if (!updateOrderRs) {
                log.warn("path：{}，errMsg：{}", getRequestUrl(), "更新订单失败");
                return R.error(400, "更新订单失败");
            }
            TerminalEntity terminalEntity = new TerminalEntity();
            terminalEntity.setRentState(0);
            boolean updateTerminalRs = terminalService.update(terminalEntity, new UpdateWrapper<TerminalEntity>().eq(FieldConstant.T_TERMINAL_IOT, terminalId));
            if (!updateTerminalRs) {
                log.warn("path：{}，errMsg：{}", getRequestUrl(), "更新机柜失败");
                return R.error(400, "更新机柜失败");
            }
            log.warn("path：{}，errMsg：{}", getRequestUrl(), "支付失败");
            return R.error("支付失败");
        }

        //预付单信息
        String prepay_id = result.get("prepay_id");

        /**
         * 小程序调起支付数据签名
         */
        Map<String, String> packageParams = new HashMap<String, String>();
        packageParams.put("appId", WxProgramPayConfig.APPID);
        packageParams.put("timeStamp", System.currentTimeMillis() / 1000 + "");
        packageParams.put("nonceStr", System.currentTimeMillis() + "");
        packageParams.put("package", "prepay_id=" + prepay_id);
        packageParams.put("signType", "MD5");
        String packageSign = WXPayUtil.generateSignature(packageParams, WxProgramPayConfig.KEY);
        packageParams.put("paySign", packageSign);
        return R.ok().put("data", packageParams);
    }
}


